import * as Cesium from "cesium"

/**
 * @参数说明:
 * @param { Viewer }  viewer
 * @param { Cartesian2 || Array } position
 * @param { Dom || `<div><button class='closeBtn'>x</button>弹窗</div>` } popDom
 * @param { Cartesian3 } location
 */

export class Popup {
  viewer: Cesium.Viewer
  id: undefined | string
  offset: [number, number]
  domInstance: HTMLElement
  position: Cesium.Cartesian3
  constructor(options: {
    id?: string
    viewer: Cesium.Viewer
    popDom: HTMLElement
    offset?: [number, number]
    position: Cesium.Cartesian3
  }) {
    //添加偏移信息
    const { offset: [x, y] = [0, 0] } = options
    this.offset = [x, y]

    //状态初始化
    this.id = options.id || String(Math.random() * 100000)
    this.viewer = options.viewer
    this.domInstance = options.popDom
    this.position = options.position //弹窗定位点世界坐标
    this.PopupDom()
    this.initPostRender()
  }

  //弹出Dom
  PopupDom() {
    this.domInstance.style.position = "absolute"
    this.domInstance.style.visibility = "visible"
    this.domInstance.style.transform = "translate(-50%, -100%)" //弹窗dom的锚点位于元素最下方的中间
    this._setDomPosition()
    this.viewer.cesiumWidget.container.appendChild(this.domInstance)
  }

  //添加场景事件
  initPostRender() {
    if (this.position) {
      this.viewer.scene.postRender.addEventListener(this.postRender, this)
    }
  }

  //实时更新弹窗位置
  postRender() {
    if (!this.domInstance || !this.domInstance.style) {
      return
    }
    this._setDomPosition()

    //控制弹窗的隐藏
    const camerPosition = this.viewer.camera.position //相机位置
    let height =
      this.viewer.scene.globe.ellipsoid.cartesianToCartographic(
        camerPosition,
      ).height //相机高度
    height += this.viewer.scene.globe.ellipsoid.maximumRadius //实时更新相机高度
    if (
      !(Cesium.Cartesian3.distance(camerPosition, this.position) > height) && //转到背面时隐藏
      this.viewer.camera.positionCartographic.height < 50000000 //当相机高度大于10000000时隐藏弹窗（默认）
    ) {
      this.domInstance.style.visibility = "visible"
    } else {
      this.domInstance.style.visibility = "hidden"
    }
  }

  //设置Dom位置
  _setDomPosition() {
    //把笛卡尔坐标转屏幕坐标
    const screenPosition = Cesium.SceneTransforms.worldToWindowCoordinates(
      this.viewer.scene,
      this.position,
    )
    if (screenPosition) {
      this.domInstance.style.top = screenPosition.y + this.offset[1] + "px"
      this.domInstance.style.left = screenPosition.x + this.offset[0] + "px"
    } else {
      console.error("从世界坐标到屏幕坐标转换失败,Popup._setDomPosition")
    }
  }

  //销毁弹窗Dom
  destroy() {
    //移除事件监听
    this.viewer.scene.postRender.removeEventListener(this.postRender, this) //移除事件监听
    //移除Dom
    this.domInstance.remove()
  }
}
